package com.sduept.nwld.dataserver.controller.fault;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.primefaces.PrimeFaces;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSONObject;
import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.enums.DeviceActionType;
import com.sduept.bigdata.fault.manager.FaultEditLockManager;
import com.sduept.bigdata.fault.report.etl.model.DeviceActionDTO;
import com.sduept.bigdata.fault.report.etl.model.DeviceActionDetailDTO;
import com.sduept.bigdata.fault.report.etl.model.ProtectionActionTimeAnalysisModel;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.nwld.wave.util.ProtectionNwUtil;
import com.sduept.permission.manager.PersonnelManager;

public class ProtectActSvgController extends AbstractController {

	/**
	 *
	 */
	private static final long serialVersionUID = -8805248815242622169L;
	@Autowired
	private FaultEditLockManager lockM;
	@Autowired
	private PersonnelManager personM;

	DecimalFormat df = new DecimalFormat("#0.0");

	// 无录波有动作元件时用此方法组织时间序列
	public JSONObject getActListByComponent(String stationName, List<DeviceActionDetailDTO> actDetailList) {
		if (isEffectiveDetailList(actDetailList)) {
			JSONObject jso = new JSONObject();
			jso.put("station", stationName);
			Map<String, List<String[]>> map = new HashMap<>();
			jso.put("value", map);
			List<String> errorList = new ArrayList<>();
			Map<String, List<String[]>> totalMap = new HashMap<>();
			jso.put("totalVal", totalMap);
			jso.put("error", errorList);
			outer: for (DeviceActionDetailDTO detail : actDetailList) {
				if (!"".equals(detail.getActionTime()) && detail.getActionTime() != 0) {
					String actName = "";
					String phase = "";
					if (StringUtils.isNotEmpty(detail.getActionCondition())) {
						actName = detail.getActionCondition().indexOf("跳") > -1 ? "跳" : "重合";
						phase = "三跳".equals(detail.getActionCondition()) ? "ABC" : detail
								.getActionCondition().replace("相", "").replace("跳", "").replace("重合", "");
					}
					String devName = detail.getProtectName().replace("线路", "").replace("断路器", "");
					if (devName.contains("主")) {
						devName = devName.replaceAll("保护", "");
					}
					// 先检查有没有重复的记录(名字相同，动作相同，相别相同，不再取该条记录)
					for (Map.Entry<String, List<String[]>> entry : map.entrySet()) {
						List<String[]> values = entry.getValue();
						for (String[] v : values) {
							if (devName.equals(v[0]) && phase.equals(v[2]) && actName.equals(v[1])) {
								continue outer;
							}
						}
					}
					int time = detail.getActionTime() * 1000;
					String actTime = time + "";
					List<String[]> act = map.get(actTime);
					String descTime = df.format((float) time / 1000);
					if (act == null) {
						act = new ArrayList<>();
						String[] s = { devName, actName, phase, phase + ":" + descTime };
						act.add(s);
						map.put(actTime, act);
					} else {
						for (int i = 0; i < act.size(); i++) {
							// 找到第一个数据组
							String[] tmparr = act.get(i);
							// 名字相同，动作相同，相别不同，合并相别
							if ((devName.equals(tmparr[0])) && (actName.equals(tmparr[1]))
									&& (!phase.equals(tmparr[2]))) {
								tmparr[2] += phase;
								tmparr[3] += "<br/>" + phase + ":" + descTime;
								break;
							} else if ((devName.equals(tmparr[0])) && (actName.equals(tmparr[1]))
									&& (phase.equals(tmparr[2]))) {
								// 名字相同，动作相同，相别相同，不取该条记录
								continue outer;
							} else if (i == act.size() - 1) {
								// 名字不同
								String[] s = { devName, actName, phase, phase + ":" + descTime };
								act.add(s);
								break;
							}
						}
					}
					List<String[]> temp = new ArrayList<String[]>();
					for (String[] s : act) {
						String[] ss = new String[s.length];
						for (int i = 0; i < s.length; i++) {
							ss[i] = new String(s[i]);
						}
						temp.add(ss);
					}
					totalMap.put(actTime, temp);
				}
			}
			return jso;
		}
		return null;
	}

	// 有录波时用此方法，组织时间序列
	public JSONObject getActTimeListByRecorder(String stationName, ProtectionActionTimeAnalysisModel proModel) {
		JSONObject jso = new JSONObject();
		List<DeviceActionDTO> breakerAct = cloneList(proModel.getBreakerActionList());
		List<DeviceActionDTO> other = cloneList(proModel.getOtherProtectionActionList());
		List<DeviceActionDTO> breakerProtect = cloneList(proModel.getBreakerProtectionActionList());
		List<DeviceActionDTO> protectAct = cloneList(proModel.getProtectionActionList());
		for (DeviceActionDTO bc : breakerAct) {
			// 处理断路器动作为断弧
			if (!getActType(bc.getJump_remark()).contains("重合")) {
				bc.setJump_remark("断弧");
			} else {
				bc.setJump_remark("重合");
			}
		}
		for (DeviceActionDTO bpc : breakerProtect) {
			String devName = bpc.getName() == null ? "" : bpc.getName();
			// 处理断路器保护的名字
			bpc.setName(ProtectionNwUtil.getBreakerOfBreakerProtect(devName) + "保护");
			bpc.setJump_remark(getActType(bpc.getJump_remark()));
			// other.add(bp);
		}
		for (DeviceActionDTO pc : protectAct) {
			// 主保护去掉保护两个字
			pc.setName(ProtectionNwUtil.getProtectionTypeLabel(pc.getName()).replaceAll("保护", ""));
			pc.setJump_remark(getActType(pc.getJump_remark()));
		}
		jso.put("station", stationName);
		Map<String, List<String[]>> map = new HashMap<>();
		jso.put("value", map);
		List<String> errorList = new ArrayList<>();
		Map<String, List<String[]>> totalMap = new HashMap<>();
		jso.put("totalVal", totalMap);
		jso.put("error", errorList);
		getData(protectAct, errorList, map, totalMap);
		getData(breakerAct, errorList, map, totalMap);
		getData(breakerProtect, errorList, map, totalMap);
		for (DeviceActionDTO p : other) {
			if ("NONE".equals(p.getPhase()) || p.getDistance_0_moments_time() <= 0) {

			} else {
				String actName = getActType(p.getJump_remark());
				// 时间相差在1ms以内的视为同一时间
				int time = p.getDistance_0_moments_time();
				int dValue = 4000;// 差值
				int minTime = time - dValue;
				int maxTime = time + dValue;
				String actTime = time + "";
				for (String str : totalMap.keySet()) {
					int t = Integer.parseInt(str);
					if (t >= minTime && t <= maxTime) {
						int d = t > time ? (t - time) : (time - t);
						if (d < dValue) {
							dValue = d;
							actTime = t + "";
						}
					}
				}
				List<String[]> act = totalMap.get(actTime);
				String descTime = df.format((float) time / 1000);
				if (act == null) {
					act = new ArrayList<>();
					String[] s = { p.getName(), actName, p.getPhase(), p.getPhase() + ":" + descTime };
					act.add(s);
				} else {
					for (int i = 0; i < act.size(); i++) {
						// 找到一个数据组
						String[] tmparr = act.get(i);
						// 名字相同，动作相同，相别不同，合并相别
						if ((p.getName().equals(tmparr[0])) && (actName.equals(tmparr[1]))) {
							tmparr[2] += p.getPhase();
							tmparr[3] += "<br/>" + p.getPhase() + ":" + descTime;
							break;
						} else if (i == act.size() - 1) {
							String[] s = { p.getName(), actName, p.getPhase(), p.getPhase() + ":" + descTime };
							act.add(s);
							break;
						}
					}
				}
				totalMap.put(actTime, act);
			}
		}
		return jso;
	}

	public List<DeviceActionDTO> cloneList(List<DeviceActionDTO> originList) {
		List<DeviceActionDTO> newList = new ArrayList<>();
		if (null != originList && originList.size() > 0) {
			for (DeviceActionDTO d : originList) {
				try {
					newList.add(d.clone());
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
		return newList;
	}

	private void getData(List<DeviceActionDTO> action, List<String> errorList,
			Map<String, List<String[]>> map, Map<String, List<String[]>> totalMap) {
		for (DeviceActionDTO p : action) {
			if (null != p) {
				if ("NONE".equals(p.getPhase()) || p.getDistance_0_moments_time() <= 0) {
					if ("重合".equals(p.getJump_remark())) {
						errorList.add(p.getName() + p.getJump_remark() + p.getPhase());
					} else {
						errorList.add(p.getName() + p.getJump_remark());
					}
				} else {
					// 动作类型（跳或者重合，断路器和断路器保护集合里存在重合闸,断路器跳闸改为断弧）
					String actName = p.getJump_remark() == null ? "" : p.getJump_remark();
					// 名字相同的，时间相差在4ms以内的视为同一时间
					int time = p.getDistance_0_moments_time();
					int dValue = 4000;// 差值
					int minTime = time - dValue;
					int maxTime = time + dValue;
					String actTime = time + "";
					for (String str : map.keySet()) {
						int t = Integer.parseInt(str);
						if (t >= minTime && t <= maxTime) {
							int d = t > time ? (t - time) : (time - t);
							if (d < dValue) {
								dValue = d;
								// 判断是否有名字相同的，有的才合并
								List<String[]> list = map.get(t + "");
								for (int i = 0; i < list.size(); i++) {
									if (list.get(i)[0].equals(p.getName())) {
										actTime = t + "";
										break;
									}
								}
							}
						}
					}
					List<String[]> act = map.get(actTime);
					String descTime = df.format((float) time / 1000);
					if (act == null) {
						act = new ArrayList<>();
						String[] s = { p.getName(), actName, p.getPhase(), p.getPhase() + ":" + descTime };
						act.add(s);
						map.put(actTime, act);
					} else {
						for (int i = 0; i < act.size(); i++) {
							// 找到第一个数据组
							String[] tmparr = act.get(i);
							// 名字相同，动作相同，相别不同，合并相别
							if ((p.getName().equals(tmparr[0])) && (actName.equals(tmparr[1]))) {
								tmparr[2] += p.getPhase();
								tmparr[3] += "<br/>" + p.getPhase() + ":" + descTime;
								break;
							} else if (i == act.size() - 1) {
								// 名字不同
								String[] s = { p.getName(), actName, p.getPhase(),
										p.getPhase() + ":" + descTime };
								act.add(s);
								break;
							}
						}
					}
					List<String[]> temp = new ArrayList<String[]>();
					for (String[] s : act) {
						String[] ss = new String[s.length];
						for (int i = 0; i < s.length; i++) {
							ss[i] = new String(s[i]);
						}
						temp.add(ss);
					}
					totalMap.put(actTime, temp);
				}
			}
		}
	}

	/**
	 * 判断是跳闸还是重合闸
	 * */
	public String getActType(String originActName) {
		String recloseFlag = DeviceActionType.reclose.toString();
		if (originActName.indexOf(recloseFlag) > -1) {
			return "重合";
		}
		return "跳";
	}

	/**
	 * 判断actionList中的数据是否有效（是否大于0）
	 * */
	public boolean isEffective(Collection<DeviceActionDTO> actList) {
		for (DeviceActionDTO deviceActionDTO : actList) {
			if (deviceActionDTO.getDistance_0_moments_time() > 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断actionList中的数据是否有效（是否大于0）
	 * */
	private boolean isEffectiveDetailList(List<DeviceActionDetailDTO> actList) {
		for (DeviceActionDetailDTO deviceActionDTO : actList) {
			if (deviceActionDTO.getActionTime() > 0) {
				return true;
			}
		}
		return false;
	}

	public void checkEditPageAct(FaultRecord record) {
		String faultId = record.getId();
		if (!checkEditPageIsUsed(faultId)) {
			addErrorMessage("该故障正在被【 " + gainOwner(faultId) + " 】编辑，请等待！");
		} else {
			PrimeFaces.current().executeScript("gotoFaultReportEdit()");
		}
	}

	private String gainOwner(String faultId) {
		String ownerId = lockM.gainOwenr(faultId);
		if ("管理员".equals(ownerId)) {
			return ownerId;
		} else {
			return personM.findPersonnelById(ownerId).getName();
		}
	}

	/**
	 * 检查故障档案是否正在被编辑
	 */
	private boolean checkEditPageIsUsed(String faultId) {
		return lockM.gainLock(faultId, new Date().getTime(), getCurrentUser().getId());
	}

}
